import time, json, traceback
from loguru import logger
from flask import g, request
from app.apis.synUpdate.update_manage import getFile
from app.metrics.authentication_tool import filter_TokenSignModulePermission, filter_onlyNeedSign, filter_onlyNeedTokenSign, filter_TokenModulePermission
from app.settings.base import plat
'''
g：global
1. g对象是专用用来保存用户的数据的
2. g对象在一次请求中，全局可以调用
生命周期:
    请求过来创建，请求结束销毁
    仅适用于单次请求，g的生命周期即一个请求的生命周期
    注：和session不同，session是多个请求都可以使用的
'''
def record_request_start_time():
    # return None
    
    g.start_time = time.time()
    url_str = request.url

    query_Img = url_str.find("/api/dish/v1/query_Img")
    query_schoolNameLogo = url_str.find("/api/server/v1/query_schoolNameLogo")
    get_file = url_str.find("/api/upgrade/v1/getFile")
    query_version = url_str.find("/api/server/v1/server_version")
    get_upgrade_apkVersion = url_str.find("/api/upgrade/v1/get_upgrade_apkVersion")
    if query_schoolNameLogo > 0 or query_Img > 0 or get_file > 0 or query_version > 0 or get_upgrade_apkVersion > 0 :
        return None

    if 'OPTIONS' == request.method:
        # logger.error(f'(...)server record_request not POST!, url={url_str}, method={request.method}')
        return ''

    requestData = request.data
    try:
        requestData = json.dumps(json.loads(requestData), ensure_ascii=False, separators=(',', ':'))
        # requestData = requestData.decode().replace('\n', '').replace('\r', '').replace(' ', '').replace('\t', '')
    except Exception:
        # logger.error(f'(......)server recv request.data not json, url={url_str}, data={str(requestData)}, method={request.method}')
        pass

    # 统一记录请求数据日志
    if len(requestData) < 21000:
        logger.info(f'(starting:)server receive, url={url_str}: {requestData}')
    else:
        logger.info(f'(starting:)eserver receive, url={url_str}: data too long, len() > 21000 bit')

    # 登录单独处理
    login = url_str.find("/api/user/v1/login")
    if login > 0:
        return filter_onlyNeedSign(requestData)

    # 仅需要登录成功即可调用的接口
    edit_pwd = url_str.find("/api/user/v1/edit_pwd")
    # 设备上报只需要校验token和sign
    pos_report = url_str.find("/api/pos/v1/pos_report")
    if edit_pwd > 0 or pos_report > 0:
        return filter_onlyNeedTokenSign(requestData)

    # 上传文件无需进行sign签名
    file_upload = url_str.find("/api/upgrade/v1/upload_apk")
    if file_upload > 0:
        return filter_TokenModulePermission(request.endpoint)

    # 统一鉴权处理
    if 'windows' == plat:
        return filter_TokenModulePermission(request.endpoint)
    
    return filter_TokenSignModulePermission(requestData, request.endpoint)


def calculate_metrics(response):
    # 统一记录回复数据日志
    url_str = request.url
    query_Img = url_str.find("/api/dish/v1/query_Img") # 获取菜品图片的时候需要过滤
    getFile = url_str.find("/api/upgrade/v1/getFile") # 下载升级包的时候需要过滤
    if getFile <= 0 and query_Img <= 0:
        responseData = response.data
        try:
            responseData = json.dumps(json.loads(responseData), ensure_ascii=False, separators=(',', ':'))
            # responseData = responseData.decode().replace('\n', '').replace('\r', '').replace(' ', '').replace('\t', '')
        except Exception:
            # logger.error(f'(......)server reply data is not json, url={url_str}, data={responseData}')
            pass

        if len(responseData) < 21000:
            logger.info(f'(ending:)server reply, url={url_str}: {responseData}')
        else:
            logger.info(f'(ending:)server reply, url={url_str}: data too long, len() > 21000 bit')

    if "start_time" not in g:
        return response

    request_duration = round((time.time() - g.start_time) * 1000, 2)
    # queries_duration = round(g.get("queries_duration", 0.0), 2)
    # queries_count = g.get("queries_count", 0.0)
    endpoint = (request.endpoint or "unknown").replace(".", "-")
    logger.info(
        f"(statistics:)"
        f"method={request.method} path={request.path} status={response.status_code}"
        f" duration={request_duration}ms",
        3.6,
        feature="f-strings")
    return response


# MockResponse = namedtuple("MockResponse",
#                           ["status_code", "content_type", "content_length"])


# def calculate_metrics_on_exception(error):
#     if error is not None:
#         logger.error(error)
#         calculate_metrics(MockResponse(500, "?", -1))
